package com.property.demo.service.impl;

import com.property.demo.model.Activity;
import com.property.demo.model.Community;
import com.property.demo.repository.ActivityRepository;
import com.property.demo.repository.CommunityRepository;
import com.property.demo.service.ActivityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class ActivityServiceImpl implements ActivityService {

    @Autowired
    private ActivityRepository activityRepository;
    
    @Autowired
    private CommunityRepository communityRepository;

    @Override
    public List<Activity> findAll() {
        return activityRepository.findAll();
    }

    @Override
    public Page<Activity> findAll(Pageable pageable) {
        return activityRepository.findAll(pageable);
    }

    @Override
    public Page<Activity> findByFilters(Long communityId, String title, String status, Pageable pageable) {
        Specification<Activity> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            if (communityId != null) {
                Join<Activity, Community> communityJoin = root.join("community");
                predicates.add(criteriaBuilder.equal(communityJoin.get("id"), communityId));
            }
            
            if (title != null && !title.isEmpty()) {
                predicates.add(criteriaBuilder.like(criteriaBuilder.lower(root.get("title")), "%" + title.toLowerCase() + "%"));
            }
            
            if (status != null && !status.isEmpty()) {
                predicates.add(criteriaBuilder.equal(root.get("status"), status));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        return activityRepository.findAll(spec, pageable);
    }

    @Override
    public Optional<Activity> findById(Long id) {
        return activityRepository.findById(id);
    }

    @Override
    public Activity save(Activity activity) {
        if (activity.getCommunity() != null && activity.getCommunity().getId() != null) {
            Optional<Community> community = communityRepository.findById(activity.getCommunity().getId());
            community.ifPresent(activity::setCommunity);
        }
        return activityRepository.save(activity);
    }

    @Override
    public Activity update(Long id, Activity activityDetails) {
        Optional<Activity> optionalActivity = activityRepository.findById(id);
        if (optionalActivity.isPresent()) {
            Activity existingActivity = optionalActivity.get();
            
            if (activityDetails.getCommunity() != null && activityDetails.getCommunity().getId() != null) {
                Optional<Community> community = communityRepository.findById(activityDetails.getCommunity().getId());
                community.ifPresent(existingActivity::setCommunity);
            }
            
            existingActivity.setTitle(activityDetails.getTitle());
            existingActivity.setContent(activityDetails.getContent());
            existingActivity.setLocation(activityDetails.getLocation());
            existingActivity.setStartTime(activityDetails.getStartTime());
            existingActivity.setEndTime(activityDetails.getEndTime());
            existingActivity.setOrganizer(activityDetails.getOrganizer());
            existingActivity.setStatus(activityDetails.getStatus());
            
            return activityRepository.save(existingActivity);
        }
        return null;
    }

    @Override
    @Transactional
    public void delete(Long id) {
        activityRepository.deleteById(id);
    }

    @Override
    @Transactional
    public void deleteAll(List<Long> ids) {
        activityRepository.deleteAllById(ids);
    }

    @Override
    public List<Activity> findByCommunityId(Long communityId) {
        Optional<Community> community = communityRepository.findById(communityId);
        return community.map(activityRepository::findByCommunity).orElse(new ArrayList<>());
    }

    @Override
    public List<Activity> findByTitleContaining(String title) {
        return activityRepository.findByTitleContaining(title);
    }

    @Override
    public List<Activity> findByStatus(String status) {
        return activityRepository.findByStatus(status);
    }
} 